package com.heima.comment.service.impl;

import com.heima.apis.article.ApArticleClient;
import com.heima.apis.user.IUserClient;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.pojos.ApCommentRepay;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.comment.vos.ApCommentsVo;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.dtos.WmCommentLikeDto;
import com.heima.model.wemedia.dtos.WmCommentListDto;
import com.heima.model.wemedia.dtos.WmCommentRepayDto;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.thread.AppThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private ApArticleClient apArticleClient;

    @Autowired
    private IUserClient iUserClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private IWemediaClient iWemediaClient;

    /**
     * 保存评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //参数校验
        if (dto==null || dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断是否登录
        Integer apUserId = AppThreadLocalUtils.getUser().getId();
        if (apUserId==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN,"请登录后评论!");
        }
        //获取文章评论状态是否可以评论
        ApArticleConfig articleConfig = apArticleClient.getArticleConfig(dto.getArticleId());
        if (!articleConfig.getIsComment()){
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH,"文章不可评论!");
        }
        //评论内容
        String content = dto.getContent();
        if (content.length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论字数超过140字!");
        }
        //评论内容校验
        boolean flag=handleCommentScan(content);
        if (!flag){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,
                    "评论中包含敏感词!");
        }
        //获取用户
        String apUserName = iUserClient.getUser(apUserId).getName();

        ApComment apComment=new ApComment();
        apComment.setAuthorId(apUserId);
        apComment.setAuthorName(apUserName);
        apComment.setEntryId(dto.getArticleId());
        apComment.setContent(content);
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setCreatedTime(new Date());
        apComment.setType(0);
        apComment.setFlag(0);
        //保存数据
        mongoTemplate.save(apComment);

        //修改文章评论数量
        kafkaTemplate.send(ArticleConstants.ARTICLE_COMMENT,dto.getArticleId().toString());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 校验评论内容
     * @param content
     * @return
     */
    private boolean handleCommentScan(String content) {
        //标记位：假设审核没问题
        boolean flag = true;
        //获取敏感词
        List<WmSensitive> allSensitive = iWemediaClient.getAllSensitive();
        List<String> list = allSensitive.stream().map(wmSensitive -> wmSensitive.getSensitives()).collect(Collectors.toList());
        //1. 初始化敏感词库
        SensitiveWordUtil.initMap(list);
        //2. 进行敏感词匹配
        Map<String, Integer> resMap = SensitiveWordUtil.matchWords(content);
        //结果处理
        if (!resMap.isEmpty()){
            flag = false;
        }
        return flag;
    }

    /**
     * 点赞/取消点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //参数校验
        if (dto==null || dto.getCommentId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //获取用户id
        Integer apUserId = AppThreadLocalUtils.getUser().getId();
        ApCommentLike apCommentLike=new ApCommentLike();
        apCommentLike.setCommentId(dto.getCommentId());
        apCommentLike.setAuthorId(apUserId);

        //获取评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        Integer likes = apComment.getLikes();
        likes=likes==null? 0: likes;

        if (dto.getOperation()==0){
            likes+=1;
            mongoTemplate.save(apCommentLike);
        }else {
            likes= likes-1<0? 0 :(likes-1);
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(dto.getCommentId())),ApCommentLike.class);
        }
        apComment.setLikes(likes);
        //条件
        Query query=new Query(Criteria.where("id").is(dto.getCommentId()));
        //修改的内容
        Update update=new Update().set("likes",likes);
        //修改
        mongoTemplate.updateFirst(query,update,ApComment.class);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentDto dto) {
        //参数校验
        if (dto==null || dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Query query=new Query();

        Criteria criteria=new Criteria();
        //多条件拼接
        criteria.andOperator(
                Criteria.where("entryId").is(dto.getArticleId())
                //Criteria.where("createdTime").lt(dto.getMinDate())
        );
        //添加条件
        query.addCriteria(criteria);

        query.limit(10);
        query.skip((dto.getIndex()-1) * 10);
        //排序
        query.with(Sort.by(
                Sort.Order.desc("createdTime")
        ));
        //获取所有评论
        List<ApComment> apCommentList = mongoTemplate.find(query, ApComment.class);
        //获取用户id
        Integer apUserId = AppThreadLocalUtils.getUser().getId();

        List<ApCommentVo> apCommentVoList=new ArrayList<>();
        //遍历所有评论
        for (ApComment apComment : apCommentList) {
            ApCommentVo apCommentVo=new ApCommentVo();
            //属性对拷
            BeanUtils.copyProperties(apComment,apCommentVo);
            //构建多条件
            Criteria criteriaLike=new Criteria();
            criteriaLike.andOperator(
                    Criteria.where("authorId").is(apUserId),
                    Criteria.where("commentId").is(apComment.getId())
            );
            //判断是否点赞
            boolean exists = mongoTemplate.exists(Query.query(criteriaLike), ApCommentLike.class);
            if (exists){
                apCommentVo.setOperation(0);
            }
            apCommentVoList.add(apCommentVo);
        }
        return ResponseResult.okResult(apCommentVoList);
    }

    /**
     * 远程获取文章评论详情
     * @param dto
     * @param apAuthorId
     * @return
     */
    @Override
    public ResponseResult getCommentList(WmCommentListDto dto,Integer apAuthorId) {
        //参数校验
        if (dto==null || dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Query query=new Query(Criteria.where("entryId").is(dto.getArticleId()));

        //添加分页
        query.skip((dto.getPage()-1)*dto.getSize()).limit(10);
        //排序
        query.with(Sort.by(
                Sort.Order.desc("createdTime")
        ));
        //获取所有评论
        List<ApComment> apCommentAllList = mongoTemplate.find(query, ApComment.class);

        //返回的集合
        List<ApCommentsVo> apCommentsVoList=new ArrayList<>();

        //遍历
        for (ApComment apComment : apCommentAllList) {
            ApCommentVo apCommentVo=new ApCommentVo();
            ApCommentsVo apCommentsVo=new ApCommentsVo();
            //属性拷贝
            BeanUtils.copyProperties(apComment,apCommentVo);
            //查询是否点赞
            //构建多条件
            Criteria criteriaLike=new Criteria();
            criteriaLike.andOperator(
                    Criteria.where("authorId").is(apAuthorId),
                    Criteria.where("commentId").is(apComment.getId())
            );
            //判断是否点赞
            boolean exists = mongoTemplate.exists(Query.query(criteriaLike), ApCommentLike.class);
            if (exists){
                apCommentVo.setOperation(0);
            }

            //查询评论下的所有回复
            List<ApCommentRepay> apCommentRepays = mongoTemplate.find(Query.query(Criteria.where("commentId")
                    .is(apComment.getId())).with(Sort.by(Sort.Order.desc("createdTime"))), ApCommentRepay.class);

            apCommentsVo.setApComments(apCommentVo);

            apCommentsVo.setApCommentRepays(apCommentRepays);
            apCommentsVoList.add(apCommentsVo);
        }
        PageResponseResult pageResponseResult=new PageResponseResult(dto.getPage(),dto.getSize(),apCommentAllList.size());
        pageResponseResult.setData(apCommentsVoList);

        return pageResponseResult;
    }

    /**
     * 自媒体端作者回复评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult commentRepay(WmCommentRepayDto dto) {
        //参数校验
        if (dto==null || dto.getCommentId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        String content = dto.getContent();
        //字数校验
        if (content.length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"回复字数不能超过140字!");
        }
        //评论内容校验
        boolean flag=handleCommentScan(content);
        if (!flag){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,
                    "评论中包含敏感词!");
        }
        ApCommentRepay apCommentRepay=new ApCommentRepay();
        ApUser apUser = iUserClient.getUser(dto.getAuthorId());

        apCommentRepay.setAuthorId(dto.getAuthorId());
        apCommentRepay.setAuthorName(apUser.getName());
        apCommentRepay.setCommentId(dto.getCommentId());
        apCommentRepay.setContent(content);
        apCommentRepay.setLikes(0);
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setUpdatedTime(new Date());
        //保存
        mongoTemplate.save(apCommentRepay);

        // 添加回复数量
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        Integer reply = apComment.getReply();
        reply= reply==null ? 1 : (reply+1);

        Query query=new Query(Criteria.where("id").is(dto.getCommentId()));
        //更新值
        Update update=new Update().set("reply",reply);
        //更新
        mongoTemplate.updateFirst(query,update,ApComment.class);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 自媒体端作者点赞/取消点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult authorLike(WmCommentLikeDto dto) {
        //校验参数
        if (dto==null || dto.getCommentId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        ApCommentLike apCommentLike=new ApCommentLike();
        apCommentLike.setCommentId(dto.getCommentId());
        apCommentLike.setAuthorId(dto.getAuthorId());

        //获取评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        Integer likes = apComment.getLikes();
        likes=likes==null? 0: likes;

        if (dto.getOperation()==0){
            likes+=1;
            mongoTemplate.save(apCommentLike);
        }else {
            likes= likes-1<0? 0 :(likes-1);
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(dto.getCommentId())),ApCommentLike.class);
        }
        apComment.setLikes(likes);
        //条件
        Query query=new Query(Criteria.where("id").is(dto.getCommentId()));
        //修改的内容
        Update update=new Update().set("likes",likes);
        //修改
        mongoTemplate.updateFirst(query,update,ApComment.class);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }
}
